package com.hibase.upms.service.user.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hibase.common.constant.ResponseCode;
import com.hibase.common.entity.MultiCallSelect;
import com.hibase.common.entity.User;
import com.hibase.common.exception.HibaseAssert;
import com.hibase.common.exception.HibaseException;
import com.hibase.common.util.EntityUtil;
import com.hibase.common.util.UserContext;
import com.hibase.core.mybatis.entity.BaseDO;
import com.hibase.core.mybatis.service.BaseServiceImpl;
import com.hibase.core.web.entity.OperationIdEntity;
import com.hibase.upms.constant.UserManagerConstant;
import com.hibase.upms.entity.menu.MdsMenu;
import com.hibase.upms.entity.organization.MdsOrganization;
import com.hibase.upms.entity.role.MdsRole;
import com.hibase.upms.entity.rolemenu.MdsRoleMenu;
import com.hibase.upms.entity.user.MdsUser;
import com.hibase.upms.entity.user.dto.MdsUserSearchVO;
import com.hibase.upms.entity.user.dto.MdsUserUpdateMultiVO;
import com.hibase.upms.entity.user.dto.MdsUserUpdateVO;
import com.hibase.upms.entity.user.vo.MdsUserRoleOpVO;
import com.hibase.upms.entity.user.vo.MdsUserRoleViewVO;
import com.hibase.upms.entity.user.vo.MdsUserVO;
import com.hibase.upms.entity.user.vo.MdsUserViewVO;
import com.hibase.upms.entity.userorg.MdsOrgUser;
import com.hibase.upms.entity.userrole.MdsUserRole;
import com.hibase.upms.mapper.user.MdsUserMapper;
import com.hibase.upms.service.menu.MdsMenuService;
import com.hibase.upms.service.organization.IMdsOrganizationService;
import com.hibase.upms.service.role.MdsRoleService;
import com.hibase.upms.service.rolemenu.MdsRoleMenuService;
import com.hibase.upms.service.user.MdsUserService;
import com.hibase.upms.service.userorg.IMdsOrgUserService;
import com.hibase.upms.service.userrole.MdsUserRoleService;
import com.hiibase.core.security.util.SecurityUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ChrisCui
 * @since 2019-04-16
 */
@Service
@Transactional(readOnly = true, rollbackFor = Exception.class)
@Slf4j
@RequiredArgsConstructor
public class MdsUserServiceImpl extends BaseServiceImpl<MdsUserMapper, MdsUser> implements MdsUserService {

    private final MdsUserRoleService userRoleService;

    private final IMdsOrgUserService orgUserService;

    private final MdsRoleMenuService roleMenuService;

    private final MdsMenuService mdsMenuService;

    private final IMdsOrganizationService mdsOrganizationService;

    private final MdsRoleService mdsRoleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MdsUser changeUser(MdsUserUpdateVO mdsUserUpdateVO) {
        MdsUser mdsUser = EntityUtil.transform(mdsUserUpdateVO, MdsUser.class);
        // 新增
        if (StrUtil.isBlank(mdsUser.getId())) {
            mdsUser.setLoginPwd(SecurityUtil.encodePassword(UserManagerConstant.USER_DEFAULT_PASSWORD));
            mdsUser.setBeActive(true);
        }
        super.store(mdsUser);
        //保存所属组织信息
        if (mdsUserUpdateVO.getOrgId() != null) {
            orgUserService.deleteBy(Wrappers.<MdsOrgUser>lambdaQuery()
                    .eq(MdsOrgUser::getUserId, mdsUser.getId()));
            MdsOrgUser orgUser = new MdsOrgUser();
            orgUser.setOrgId(mdsUserUpdateVO.getOrgId());
            orgUser.setUserId(mdsUser.getId());
            orgUserService.store(orgUser);
        }
        //保存用户下角色信息
        insAndDelUserRole(mdsUser.getId(), mdsUserUpdateVO.getRoleId());
        return mdsUser;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MdsUser changeUser(MdsUserUpdateMultiVO mdsUserUpdateMultiVO) {
        MdsUserUpdateVO updateVO = EntityUtil.transform(mdsUserUpdateMultiVO, MdsUserUpdateVO.class);
        updateVO.setRoleId(mdsUserUpdateMultiVO.getRoleList()
                .stream().map(MultiCallSelect::getId)
                .collect(Collectors.toList()));
        return this.changeUser(updateVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeUserStatus(List<String> ids, boolean recordStatusEnable) {
        List<MdsUser> userList = super.listByIds(ids);
        userList.forEach(user -> {
            HibaseAssert.isFalse(user.getBeActive() == recordStatusEnable,
                    "{} 请勿重复操作", user.getLoginName());
            user.setBeActive(recordStatusEnable);
        });
        if (CollUtil.isNotEmpty(userList)) {
            super.storeBatch(userList);
        }
    }

    @Override
    public PageInfo<MdsUserVO> selectList(MdsUserSearchVO searchVO) {
        Map<String, Object> conditionMap = new HashMap<>();
        if (StrUtil.isNotBlank(searchVO.getSysName())) {
            conditionMap.put("sysName", searchVO.getSysName());
        }
        if (StrUtil.isNotBlank(searchVO.getLoginName())) {
            conditionMap.put("loginName", searchVO.getLoginName());
        }
        if (StrUtil.isNotBlank(searchVO.getMobile())) {
            conditionMap.put("mobile", searchVO.getMobile());
        }
        if (StrUtil.isNotBlank(searchVO.getOrgId())) {
            conditionMap.put("orgId", searchVO.getOrgId());
        }
        if (StrUtil.isNotBlank(searchVO.getKeyWord())) {
            conditionMap.put("keyWord", "%" + searchVO.getKeyWord().trim() + "%");
        }
        Page<MdsUserVO> page = PageHelper.startPage(searchVO.getCurrentPage(), searchVO.getPageSize());
        this.baseMapper.selectUserList(conditionMap);
        return new PageInfo<>(page);
    }

    @Override
    public PageInfo<MdsUserRoleViewVO> selectUserRoleList(OperationIdEntity idEntity) {
        Map<String, Object> conditionMap = new HashMap<>();
        if (StrUtil.isNotBlank(idEntity.getId())) {
            conditionMap.put("id", idEntity.getId());
        }
        Page<MdsUserRoleViewVO> page = PageHelper.startPage(idEntity.getCurrentPage(), idEntity.getPageSize());
        this.baseMapper.selectUserRoleList(conditionMap);
        return new PageInfo<>(page);
    }

    @Override
    public PageInfo<MdsUserRoleViewVO> selectUserNoRoleList(OperationIdEntity idEntity) {
        Map<String, Object> conditionMap = new HashMap<>();

        if (StrUtil.isNotBlank(idEntity.getId())) {
            conditionMap.put("id", idEntity.getId());
        }

        Page<MdsUserRoleViewVO> page = PageHelper.startPage(idEntity.getCurrentPage(), idEntity.getPageSize());

        this.baseMapper.selectUserNoRoleList(conditionMap);
        PageInfo<MdsUserRoleViewVO> result = new PageInfo<>(page);

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteUserRole(MdsUserRoleOpVO mdsUserRoleOpVo) {

        if (CollUtil.isNotEmpty(mdsUserRoleOpVo.getRoleId())) {
            for (String roleId : mdsUserRoleOpVo.getRoleId()) {
                MdsUserRole userRole = userRoleService.getOne(new QueryWrapper<MdsUserRole>().eq("user_id", mdsUserRoleOpVo.getUserId()).eq("role_id", roleId));
                if (ObjectUtils.isNull(userRole)) {
                    throw new HibaseException(ResponseCode.DATA_NOT_EXISTS.getCode(), ResponseCode.DATA_NOT_EXISTS.getMessage());
                }
                userRoleService.deleteBy(userRole);
            }
        }
    }

    private void insAndDelUserRole(String userId, List<String> roleIds) {
        // 先删除此用户对应的角色旧数据
        if (StrUtil.isNotBlank(userId)) {
            userRoleService.deleteBy(Wrappers.<MdsUserRole>lambdaQuery()
                    .eq(MdsUserRole::getUserId, userId));
        }
        // 保存角色
        List<MdsUserRole> userRoleList = new ArrayList<>();
        if (CollUtil.isNotEmpty(roleIds)) {
            for (String roleId : roleIds) {
                MdsUserRole mdsUserRole = new MdsUserRole();
                mdsUserRole.setUserId(userId);
                mdsUserRole.setRoleId(roleId);
                userRoleList.add(mdsUserRole);
            }
            userRoleService.storeBatch(userRoleList);
        }
    }

    @Override
    public MdsUser checkLoginUser(String userName, String password) {

        QueryWrapper<MdsUser> wrapper = new QueryWrapper<>();

        wrapper.eq("login_name", userName);

        MdsUser oldUser = super.getOne(wrapper);


        if (ObjectUtils.isNull(oldUser)) {

            throw new HibaseException(ResponseCode.ADMIN_USER_NOT_EXISTS.getCode(), ResponseCode.ADMIN_USER_NOT_EXISTS.getMessage());
        }

        // 对比密码
        String pwd = SecurityUtil.encodePassword(password);
        if (!pwd.equals(oldUser.getLoginPwd())) {

            throw new HibaseException(ResponseCode.ADMIN_USER_PASSWORD_ERROR.getCode(), ResponseCode.ADMIN_USER_PASSWORD_ERROR.getMessage());
        }

        if (oldUser.getBeActive() != null && !oldUser.getBeActive()) {

            throw new HibaseException(ResponseCode.ADMIN_USER_DISABLED.getCode(), ResponseCode.ADMIN_USER_DISABLED.getMessage());
        }

//        WmsWarehouse warehouse = wmsWarehouseService.getById(oldUser.getRelationWarehouse(), false);
//        if(ObjectUtil.isNotEmpty(warehouse)){
//            oldUser.setTimeZone(warehouse.getTimeZone());
//        }

        // 校验当前用户是否有可用角色
        this.checkAvailableRole(oldUser.getId());

        // 设置组织和所属平台
        setDataPerm(oldUser);

        return oldUser;
    }

    /**
     * 校验当前用户是否有可用角色
     */
    private void checkAvailableRole(String userId) {

        HibaseAssert.notEmpty(userRoleService.selectRoleIdByCurrentUser(userId), "service.mds.user.impl.mdsUserServiceImpl.userHasNoPermission");
    }

    /**
     * 设置组织和所属平台
     */
    private void setDataPerm(MdsUser oldUser) {

        // 查询当前用户所在的组织全路径
//        MdsOrgUserDV mdsOrgUser = orgUserService.selectUserOrgFullIds(oldUser.getId());
//
//        HibaseAssert.notNull(mdsOrgUser, "service.mds.user.impl.mdsUserServiceImpl.noAffiliation");
//
//        oldUser.setOrgId(mdsOrgUser.getOrgId());
//        oldUser.setOrgFullId(mdsOrgUser.getParentIds());
//
//        if (StrUtil.isNotBlank(oldUser.getOrgId())) {
//
//            int index = oldUser.getOrgId().indexOf("/");
//            if (index > 0) {
//
//                oldUser.setPlatformId(oldUser.getOrgId().substring(0, index));
//            } else {
//
//                oldUser.setPlatformId(oldUser.getOrgId());
//            }
//        }
    }

    /**
     * 根据用户名称获取当前用户的所拥有的角色集合
     */
    @Override
    public List<String> selectRoleInfosByUserName(String userName) {

        return super.getBaseMapper().selectRoleInfosByUserName(userName);
    }

    @Override
    public List<String> selectPermissionsByUserName(String userName) {
        return super.getBaseMapper().selectPermissionsByUserName(userName);
    }

    @Override
    public List<String> selectNameByUserName(String userName) {
        return super.getBaseMapper().selectNameByUserName(userName);
    }

    /**
     * 用户修改密码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePasswd(String oldPasswd, String newPasswd) {
        // 校验旧密码是否正确
        User user = UserContext.get();
        // 查询用户信息
        MdsUser userInfo = super.getById(user.getId());
        HibaseAssert.isTrue(SecurityUtil.matchesPassword(oldPasswd, userInfo.getLoginPwd()),
                "旧密码不正确");
        String encryNewPasswd = SecurityUtil.encodePassword(newPasswd);
        userInfo.setLoginPwd(encryNewPasswd);
        log.info("用户 {} 将密码由 {} 修改为 {} ", user.getLoginName(), oldPasswd, newPasswd);
        super.store(userInfo);
    }

    /**
     * 重置密码
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPasswd(String id, String password) {
        MdsUser mdsUser = super.getById(id, true);
        mdsUser.setLoginPwd(SecurityUtil.encodePassword(password));
        super.store(mdsUser);
    }

    @Override
    public MdsUserVO selectUserById(String id) {
        Map<String, Object> conditionMap = new HashMap<>();
        conditionMap.put("userId", id);
        MdsUserVO MdsUserVO = this.baseMapper.selectUser(conditionMap);
        //设置roleList
        List<MdsUserRole> userRoleList = userRoleService.list(Wrappers.<MdsUserRole>lambdaQuery()
                .eq(MdsUserRole::getUserId, MdsUserVO.getId())
                .select(MdsUserRole::getRoleId)
        );
        if (CollUtil.isNotEmpty(userRoleList)) {
            List<String> ids = userRoleList.stream().map(MdsUserRole::getRoleId).collect(Collectors.toList());
            MdsUserVO.setRoleId(ids);
            Collection<MdsRole> roles = mdsRoleService.listByIds(ids);
            MdsUserVO.setRoleList(roles.stream().map(role -> {
                return new MultiCallSelect() {{
                    setId(role.getId());
                    setShowName(role.getName());
                }};
            }).collect(Collectors.toList()));
        }
        return MdsUserVO;
    }

    @Override
    public MdsUserViewVO viewDetails(String id) {
        MdsUserVO mdsUser = this.selectUserById(id);
        MdsUserViewVO mdsUserViewVo = EntityUtil.transform(mdsUser, MdsUserViewVO.class);
        mdsUserViewVo.setOrgId_showName(mdsUserViewVo.getOrgName());
        return mdsUserViewVo;
    }

    @Override
    public String selectRoleIdByCode(String code) {
        return userRoleService.selectRoleIdByCode(code);
    }

    @Override
    public List<String> selectPossessMenusList() {
        String userId = UserContext.get().getId();
        List<String> roleIdList = userRoleService.selectRoleIdByCurrentUser(userId);
        HibaseAssert.isFalse(CollectionUtil.isEmpty(roleIdList), "User does not have permission");
        List<MdsRoleMenu> roleMenuList = roleMenuService.list(new QueryWrapper<MdsRoleMenu>().in("role_id", roleIdList));
        List<String> menuIdList = roleMenuList.stream().map(MdsRoleMenu::getMenuId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(menuIdList)) {
            return mdsMenuService.listByIds(menuIdList).stream().map(MdsMenu::getCode).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public PageInfo selectChildUserList(MdsUserSearchVO searchVO) {
        // step01 查询当前用户所在组织
        String currentUserId = UserContext.get().getId();
        MdsOrgUser currentOrgUser = orgUserService.getOne(Wrappers.<MdsOrgUser>lambdaQuery()
                .eq(MdsOrgUser::getUserId, currentUserId)
        );
        // step02 查询当前组织的所有下级组织
        List<MdsOrganization> list = mdsOrganizationService.list();
        List<MdsOrganization> result = ListUtil.toList();
        List<MdsOrganization> childOrg = mdsOrganizationService.recursionOrg(currentOrgUser.getOrgId(), list, result);
        // step03 查询所有组织下的所有用户
        if (CollUtil.isNotEmpty(childOrg)) {
            List<MdsOrgUser> orgUserList = orgUserService.list(Wrappers.<MdsOrgUser>lambdaQuery()
                    .in(MdsOrgUser::getOrgId, childOrg.stream().map(BaseDO::getId).collect(Collectors.toList()))
                    .select(MdsOrgUser::getUserId)
            );
            if (CollUtil.isNotEmpty(orgUserList)) {
                return super.page(searchVO, Wrappers.<MdsUser>query()
                        .in("id", orgUserList.stream().map(MdsOrgUser::getUserId).collect(Collectors.toList()))
                );
            }
        }
        return new PageInfo(PageHelper.startPage(searchVO.getCurrentPage(), searchVO.getPageSize()));
    }
}
